home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Deutsche Edition 1
/
Deutsche Edition 1.iso
/
amok
/
081-090
/
amok85
/
trechner
/
function.mod
< prev
next >
Wrap
Text File
|
1993-11-04
|
10KB
|
303 lines
(*--------------------------------------------------------------------------
:Program. function.mod
:Contents. Funktionsparser
:Author. Frank Lömker
:Copyright. FreeWare, siehe Dok-File für TRechner
:Language. Modula-2
:Translator. M2Amiga V4.1d
:History. V1.0, [Frank Lömker] 01-Mar-93
:Bugs. keine bekannt
--------------------------------------------------------------------------*)
IMPLEMENTATION MODULE function;
(*$ DEFINE FFP:=TRUE DEFINE LONG:=FALSE *)
(*$ StackParms:=FALSE StackChk:=FALSE RangeChk:=FALSE OverflowChk:=FALSE
CaseChk:=FALSE ReturnChk:=FALSE EntryClear:=FALSE LargeVars:=FALSE
Volatile:=FALSE *)
FROM SYSTEM IMPORT ADR,ADDRESS;
FROM String IMPORT Length,Occurs,CapString;
FROM Conversions IMPORT StrToVal;
FROM (*$ IF FFP *) MathTrans
(*$ ELSIF LONG *) MathIEEEDoubTrans
(*$ ELSE *) MathIEEESingTrans (*$ ENDIF *)
IMPORT Sin,Cos,Tan,Sqrt,Log,Pow,Exp,Atan,Asin,Acos,Tanh,Sinh,Cosh,Log10;
FROM (*$ IF FFP *) FFPConversions
(*$ ELSIF LONG *) LongRealConversions
(*$ ELSE *) RealConversions (*$ ENDIF *) IMPORT StrToReal;
(*$ IF FFP *)
CONST factMax=20.0; (* FFP *)
winMax=102900.0;
expMax=43.66;
(*$ ELSIF LONG *)
CONST factMax=170.0; (* LONGREAL *)
winMax=10000000000000.0;
expMax=709.78;
(*$ ELSE *)
CONST factMax=34.0; (* REAL *)
winMax=10000000000000.0;
expMax=88.72;
(*$ ENDIF *)
PROCEDURE calcex (ex:ARRAY OF CHAR;x:REAL;VAR y:REAL;VAR error:SHORTINT);
PROCEDURE summand():REAL; FORWARD;
PROCEDURE faktor():REAL; FORWARD;
PROCEDURE potenz():REAL; FORWARD;
VAR sym,pos:INTEGER;
ch:CHAR;
wert:REAL;
einfach:ARRAY [0..20] OF CHAR;
mehrfach:ARRAY [0..100] OF CHAR;
PROCEDURE getch;
BEGIN
REPEAT
IF pos<=Length(ex) THEN
ch:=ex[pos];
INC(pos);
ELSE
ch:=0C;
END;
UNTIL ch#" ";
END getch;
PROCEDURE getsym;
VAR anz,stelle:INTEGER;
wert2:LONGINT;
mehr:ARRAY [0..20] OF CHAR;
err,signed:BOOLEAN;
altch:CHAR;
BEGIN
altch:=ch;
wert:=0.0; mehr:="";
anz:=0;
WHILE (einfach[anz]#ch) AND (anz<=9) DO
INC(anz); END;
IF (anz<=9) AND ( (ex[pos]<"A") OR (ex[pos]>"Z") OR (anz<8) ) THEN
sym:=anz; getch;
ELSIF ch>="A" THEN (* Funktion (mehrfach) ? *)
stelle:=0;
WHILE (ch>="A") AND (ch<="Z") AND (stelle<20) DO
mehr[stelle]:=ch;
INC (stelle);
getch;
END;
mehr[stelle]:=0C;
sym:=Occurs(mehrfach,0,mehr,FALSE);
IF (sym=-1) OR (stelle<2) THEN sym:=-1; (* Fehler *)
ELSE
stelle:=sym+Length(mehr);
IF (mehrfach[sym-1]=" ") AND (mehrfach[stelle]=" ") THEN
sym:=sym DIV 5+11;
ELSE sym:=-1; END; (* Fehler *)
END;
ELSE (* Zahl ? *)
stelle:=0; anz:=10; (* = Basis *)
IF ch="$" THEN
anz:=16; getch;
ELSIF ch="%" THEN
anz:=2; getch;
END;
WHILE ((ch=".") OR ((ch>="0") AND (ch<="9")) OR
((ch>="A") AND (ch<="F")) ) AND (stelle<20) DO
mehr[stelle]:=ch;
INC(stelle);
getch;
END;
mehr[stelle]:=0C;
IF stelle=0 THEN sym:=-1; (* Fehler *)
ELSE
sym:=10;
IF anz=10 THEN
StrToReal (mehr,wert,err);
ELSE
StrToVal (mehr,wert2,signed,anz,err);
IF wert2<0 THEN sym:=-1;
ELSE wert:=REAL(wert2); END;
END;
IF err THEN sym:=-1; END;
END;
END;
IF (sym=-1) AND (altch#0C) THEN error:=wrongSym; END;
END getsym;
PROCEDURE expression():REAL;
VAR neuwert,geswert:REAL;
osym:INTEGER;
BEGIN
CASE sym OF
3: getsym; geswert:=summand(); (* + *)
|4: getsym; geswert:=-summand(); (* - *)
ELSE geswert:=summand();
END;
WHILE (sym=3) OR (sym=4) DO (* +,- *)
osym:=sym; getsym;
neuwert:=summand();
IF osym=3 THEN geswert:=geswert+neuwert;
ELSE geswert:=geswert-neuwert; END;
END;
RETURN geswert;
END expression;
PROCEDURE summand():REAL;
VAR neuwert,geswert:REAL;
osym:INTEGER;
BEGIN
geswert:=potenz();
WHILE (sym=5) OR (sym=6) DO (* *,/ *)
osym:=sym; getsym;
neuwert:=potenz();
IF osym=5 THEN geswert:=geswert*neuwert;
ELSE
IF neuwert=0.0 THEN error:=Fehler
ELSE geswert:=geswert/neuwert; END;
END;
END;
RETURN geswert;
END summand;
PROCEDURE potenz():REAL;
VAR neuwert,geswert:REAL;
osym:INTEGER;
BEGIN
geswert:=faktor();
WHILE sym=7 DO (* ^ *)
getsym;
neuwert:=faktor();
IF (geswert=0.0) AND (neuwert<=0.0) THEN (* 0^(-ZAHL) *)
error:=Fehler
ELSE
IF (geswert<0.0) THEN (* -ZAHL^ZAHL *)
IF (neuwert=REAL(INTEGER(neuwert))) THEN (* -ZAHL^n *)
IF (ODD(INTEGER(neuwert))) THEN (* -ZAHL^(n ungrade) *)
geswert:=-(Pow(geswert,neuwert))
ELSE
geswert:=Pow(geswert,neuwert);
END;
ELSE
error:=Fehler;
END;
ELSE
geswert:=Pow(geswert,neuwert);
END;
END; (* IF (geswert=0.0) *)
END; (* WHILE *)
RETURN geswert;
END potenz;
PROCEDURE Fact (x:REAL):REAL;
VAR anz:INTEGER;
BEGIN
IF (x>factMax) OR (x<0.0) OR (x#REAL(LONGINT(x))) THEN
error:=Fehler; RETURN x;
END;
anz:=INTEGER(x);
IF anz<2 THEN RETURN 1.0; END;
x:=1.0;
REPEAT
x:=x*REAL(anz);
DEC (anz);
UNTIL anz<2;
RETURN x;
END Fact;
PROCEDURE faktor():REAL;
VAR neuwert:REAL;
osym:INTEGER;
BEGIN
CASE sym OF
0: neuwert:=x; (* x *)
getsym;
| 1: getsym; (* ( *)
neuwert:=expression();
IF sym=2 THEN getsym;
ELSIF error=noFehler THEN error:=Klammerzu; END;
| 8: neuwert:=e;
getsym;
| 9: neuwert:=pi;
getsym;
|10: neuwert:=wert; (* Zahl *)
getsym;
|11..29: osym:=sym; (* Funkionen *)
getsym;
IF sym=1 THEN (* ( *)
getsym;
neuwert:=expression();
IF sym=2 THEN getsym;
ELSIF error=noFehler THEN error:=Klammerzu; END;
IF error=noFehler THEN
CASE osym OF
11: IF neuwert>winMax THEN error:=Fehler; (* sin *)
ELSE neuwert:=Sin(neuwert); END;
|12: IF neuwert>winMax THEN error:=Fehler; (* cos *)
ELSE neuwert:=Cos(neuwert); END;
|13: IF neuwert>winMax THEN error:=Fehler; (* tan *)
ELSE neuwert:=Tan(neuwert); END;
|14: IF neuwert<=0.0 THEN error:=Fehler; (* LN *)
ELSE neuwert:=Log(neuwert); END;
|15: IF neuwert<0.0 THEN error:=Fehler; (* sqrt *)
ELSE neuwert:=Sqrt(neuwert); END;
|16: neuwert:=ABS(neuwert); (* ABS *)
|17: IF neuwert>expMax THEN error:=Fehler; (* exp *)
ELSE neuwert:=Exp(neuwert); END;
|18: neuwert:=Atan(neuwert); (* ArcTan *)
|19: IF (neuwert<-1.0) OR (neuwert>1.0) THEN error:=Fehler;
ELSE neuwert:=Asin(neuwert); END; (* ArcSin *)
|20: IF (neuwert<-1.0) OR (neuwert>1.0) THEN error:=Fehler;
ELSE neuwert:=Acos(neuwert); END; (* ArcCos *)
|21: neuwert:=Tanh(neuwert); (* TanH *)
|22: neuwert:=Sinh(neuwert); (* SinH *)
|23: neuwert:=Cosh(neuwert); (* CosH *)
|24: neuwert:=(neuwert/pi*180.0); (* RToD *)
|25: neuwert:=(neuwert/180.0*pi); (* DToR *)
|26: IF neuwert<0.0 THEN neuwert:=-1.0; (* SGN *)
ELSIF neuwert>0.0 THEN neuwert:=1.0
ELSE neuwert:=0.0; END;
|27: neuwert:=Fact(neuwert); (* Fact *)
|28: IF neuwert<=0.0 THEN error:=Fehler; (* Log *)
ELSE neuwert:=Log10(neuwert); END;
|29: IF neuwert>2147000000.0 THEN error:=Fehler;
ELSE neuwert:=REAL(LONGINT(neuwert)); END; (* INT *)
END; (* CASE osym *)
END; (* IF error:=noFehler *)
ELSE
error:=Klammerauf;
END;
ELSE
error:=wrongSym;
END; (* CASE sym *)
RETURN neuwert;
END faktor;
BEGIN
y:=0.0;
einfach:="X()+-*/^EP";
(* ,1234,1234,1234,1234,1234,1234,1234,1234,1234,1234,1234,1234 *)
mehrfach:=" SIN COS TAN LN SQRT ABS EXP ATAN ASIN ACOS TANH SINH"+
" COSH RTOD DTOR SGN FACT LOG INT ";
CapString (ex);
pos:=Length(ex);
WHILE ex[pos]=" " DO
ex[pos]:=0C; DEC (pos);
END;
pos:=0;
error:=noFehler; sym:=-1;
getch; (* ex,pos,ch *)
IF ch#0C THEN
getsym; (* ex,pos,ch,sym,wert *)
y:=expression();
END;
IF error=noFehler THEN
IF sym=2 THEN error:=Klammerauf;
ELSIF (ch#0C) OR (sym#-1) THEN
error:=Fehler;
END;
END;
END calcex;
END function.